// 1-4. 命名空间-嵌套的命名空间
/**
 * C++ 命名空间
 * 假设这样一种情况，当一个班上有两个名叫 Zara 的学生时，为了明确区分它们，我们在使用名字之外，不得不使用一些额外的信息，比如他们的家庭住址，或者他们父母的名字等等。

 * 同样的情况也出现在 C++ 应用程序中。例如，您可能会写一个名为 xyz() 的函数，在另一个可用的库中也存在一个相同的函数 xyz()。这样，编译器就无法判断您所使用的是哪一个 xyz() 函数。

 * 因此，引入了命名空间这个概念，专门用于解决上面的问题，它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上，命名空间就是定义了一个范围。

 * 我们举一个计算机系统中的例子，一个文件夹(目录)中可以包含多个文件夹，每个文件夹中不能有相同的文件名，但不同文件夹中的文件可以重名。

                            文件夹A
                          ↙       ↘
                    文件夹B          文件夹C
                    ↙ ↘             ↙   ↘
            runoob-2   runoob      runoob   runoob-3
            .txt文件   .txt文件    .txt文件   .txt文件
                       |            |
                       —不同文件夹可以—
                        有相同名字的文件

 *-----------------------------------------
 * 嵌套的命名空间
 * 命名空间可以嵌套，您可以在一个命名空间中定义另一个命名空间，如下所示：

            namespace namespace_name1 {
              // 代码声明
              namespace namespace_name2 {
                  // 代码声明
              }
            }

 * 您可以通过使用 :: 运算符来访问嵌套的命名空间中的成员：

            // 访问 namespace_name2 中的成员
            using namespace namespace_name1::namespace_name2;
            
            // 访问 namespace_name1 中的成员
            using namespace namespace_name1;

 * 在上面的语句中，如果使用的是 namespace_name1，那么在该范围内 namespace_name2 中的元素**也是可用**的，
*/

#include <iostream>
namespace s1
{
  void func()
  {
    std::cout << "s1 func" << std::endl;
  }
  int a1 = 1;
  int a = 1;
  namespace s1_1
  {
    int a2 = 2;
    int a = 2;
    void func()
    {
      std::cout << "s1_1 func" << std::endl;
      std::cout << "a1 : " << a1 << std::endl;
      std::cout << "a2 : " << a2 << std::endl;
      std::cout << "a : " << a << std::endl;
      std::cout << "s1_1::a : " << s1_1::a << std::endl;
      std::cout << "s1::a : " << s1::a << std::endl;
    }
  }
}

int main(void)
{
  // using namespace s1;
  // func();
  // s1_1::func();
  using namespace s1::s1_1;
  func();

  printf("-----------------end----------------\n");
  return 0;
}